package com.synygy.bdviewer.dao;

import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.Session;
import com.synygy.bdviewer.model.STIObject;
import com.synygy.bdviewer.util.QueryParam;

import java.util.List;
import java.util.Iterator;

public class HibernateSTIObjectDao implements STIObjectDao {

    private SessionFactory sessionFactory;

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    protected Session getSession() {
		return sessionFactory.getCurrentSession();
	}

    public STIObject load(int id) {
        return (STIObject) getSession().get(STIObject.class, id);
    }

    /**
     * Save the STIObject to the DB
     *
     * @param stiObject
     * @return persistent instance of stiObject
     */
    public STIObject save(STIObject stiObject) {
        return (STIObject) getSession().merge(stiObject);
    }

    /**
     * Delete a {@link com.synygy.bdviewer.model.STIObject} from the DB, given it's <tt>id</tt>.
     *
     * @param id The id of the STIObject to delete.
     */
    public void delete(int id) {
        getSession().delete(load(id));
    }

    /**
     * Query the DB, using the supplied query details.
     *
     * @param qp Query Paramaters to use.
     * @return The results of the query as an Iterator.
     */
    public Iterator<STIObject> find(QueryParam qp, STIObject filter) {
        return buildFindQuery(qp, filter, false).list().iterator();
    }

    /**
     * Return the number of STIObjects in the DB.
     *
     * @return count
     */
    public int count(STIObject filter) {
        return ((Long) buildFindQuery(null, filter, true).uniqueResult())
                .intValue();
    }

    /**
     * Returns the list of all unique last names in the database
     *
     * @return the list of all unique last names in the database
     */
    public List<String> getUniqueLastNames() {
        return getSession().createQuery(
                "select distinct target.lastname "
                        + " from STIObject target order by target.lastname")
                .list();
    }

    /**
     * builds a query object to satisfy the provided parameters
     *
     * @param qp     sorting and paging criteria
     * @param filter filter criteria
     * @param count  true if this is a query meant to retrieve the number of rows
     * @return query object that satisfies the provided criteria
     */
    public Query buildFindQuery(QueryParam qp, STIObject filter, boolean count) {
        HibernateContactFinderQueryBuilder builder = new HibernateContactFinderQueryBuilder();
        builder.setQueryParam(qp);
        builder.setFilter(filter);
        builder.setCount(count);
        Query query = getSession().createQuery(builder.buildHql());
        query.setParameters(builder.getParameters(), builder.getTypes());
        if (!count && qp != null) {
            query.setFirstResult(qp.getFirst()).setMaxResults(qp.getCount());
        }
        return query;
    }

}
